from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from decorator.decorator import check_login
import time,redis
from users.models import Addr
from .models import Order,OrderGood
from goods.models import Good
from datetime import datetime
from django.db import transaction
from alipay import AliPay
from django.conf import settings
# Create your views here.

# 读取app 私钥
app_private_key_string = open(settings.APP_PRIVATE_KEY_PATH,'r').read()

# 读取支付宝公钥
alipay_public_key_string = open(settings.ALIPAY_PUBLIC_KEY_PATH,'r').read()

# 定义自己的视图类
class MyAlipay(APIView):
    def __init__(self, *args, **kwargs):
        # 继承父类的初始化部分
        super().__init__(*args, **kwargs)

        # 自己定义
        self.alipay = AliPay(
            appid='2021000119634123',
            app_private_key_string=app_private_key_string,
            alipay_public_key_string=alipay_public_key_string,
            app_notify_url=None,
            sign_type='RSA2',
            debug=True, # 所有的请求 定向到沙箱服务
        )

    def get_pay_url(self, order_id, total_amount):
        # 订单字符串
        order_string = self.alipay.api_alipay_trade_page_pay(
            subject="商家收款",
            out_trade_no=order_id,
            total_amount=total_amount,
            return_url="http://127.0.0.1:8000/pay/result/",
            notify_url="http://127.0.0.1:8000/pay/result/",
        )

        # 支付地址
        return 'https://openapi.alipaydev.com/gateway.do?' + order_string


# 订单类的视图
class OrderAPIView(MyAlipay):

    # 创建订单
    # def post(self,request):
    #     # 1.获取用户对象
    #     user = request.user
    #     # 2.获取前端数据
    #     products_list = request.data.get("productsArr")
    #     addr_id = request.data.get("addrID")
    #     pay_method = request.data.get("payMethod")
    #     # 3.构造 订单所需数据， 如 order_id
    #     order_id = str(time.time()).replace(".","") + "_%s"%user.id
    #
    #     # 查询地址对象
    #     try:
    #         addr = Addr.objects.get(id=addr_id)
    #     except:
    #         return Response({"code":204,'msg':'收货地址不存在'})
    #
    #     total_amount = 0
    #     total_count = 0
    #     freight = 10
    #     # 4.创建订单对象
    #     order = Order.objects.create(order_id=order_id, user=user, addr=addr, total_amount=total_amount,
    #                                  total_count=total_count, freight=freight, pay_method=pay_method, pay_status="0")
    #     # 5.创建订单商品对象， 注意 加购的商品数量必须 <= 商品的库存量
    #     for product in products_list:
    #         print("加购的商品:", product)
    #         try:
    #             good = Good.objects.get(id=product.get("productID"))
    #             # 原来的库存
    #             origin_stock = good.stock
    #             # 原来的销量
    #             origin_count = good.count
    #         except:
    #             return Response({"code":204, 'msg':'商品已下架'})
    #
    #         # 判断加购的商品数量 是否 小于等于 该商品的库存量
    #         if product.get("num") > good.stock:
    #             return Response({"code":204, 'msg':'库存不足，创建订单失败'})
    #
    #         # 正常创建订单， 创建订单商品对象
    #         OrderGood.objects.create(good=good, count=product.get("num"), price=good.selling_price, order=order)
    #
    #         # 更新当前商品的库存、销量
    #         good.stock = origin_stock - product.get("num")
    #         good.count = origin_count + product.get("num")
    #         good.save()
    #
    #         # 统计 订单中的总价格、总商品数
    #         total_count += product.get('num')
    #         total_amount += product.get('num')*good.selling_price
    #
    #     # 更新订单对象
    #     order.total_amount = total_amount
    #     order.total_count = total_count
    #     order.save()
    #
    #     # 6.删除已经购物车中已经下了订单的商品
    #     redis_conn = redis.Redis(host='localhost', port=6379, db=0, password='123')
    #     cart_key = "cart:%s"%user.id
    #     cart_selected_key = 'cart_selected:%s'%user.id
    #
    #     # 遍历加购的商品， 从redis购物车中逐一删除
    #     for i in products_list:
    #         redis_conn.hdel(cart_key, i.get('productID'))
    #         redis_conn.srem(cart_selected_key, i.get("productID"))
    #
    #     redis_conn.close()
    #
    #     # 7.返回响应
    #     return Response({'code':201, 'msg':'创建订单成功'})


    # 创建订单---事务版
    @check_login
    def post(self,request):
        # 1.获取用户对象
        user = request.user
        # 2.获取前端数据
        products_list = request.data.get("productsArr")
        addr_id = request.data.get("addrID")
        pay_method = request.data.get("payMethod")

        # 3.准备创建订单 需要的数据
        order_id = datetime.now().strftime("%Y%m%d%H%M%S") + "_%s"%user.id

        # 查询地址对象
        try:
            addr = Addr.objects.get(id=addr_id)
        except:
            return Response({"code":204, 'msg':'收货地址不存在'})

        total_amount = 0
        total_count = 0
        freight = 0

        # 4.开启事务, 并创建订单
        with transaction.atomic():
            # 创建事务回滚点
            point = transaction.savepoint()

            # 5.创建订单数据
            try:
                # 5.1插入订单数据
                order = Order.objects.create(order_id=order_id, user=user, addr=addr, total_amount=total_amount,
                                             total_count=total_count, freight=freight, pay_method=pay_method, pay_status="0")

                # 插入订单商品数据
                for i in products_list:
                    flag = 0
                    while flag < 3:
                        try:
                            good = Good.objects.get(id=i.get("productID"))
                            origin_stock = good.stock
                            origin_count = good.count
                            # raise ValueError("查询商品异常")
                        except:
                            raise ValueError("商品已下架")

                        # 判断加购的商品数 是否<=商品库存
                        num = i.get("num")
                        if num > origin_stock:
                            return ValueError("库存不足,创建订单失败")

                        # 判断商品库存、销量 前后是否一致
                        good_queryset = Good.objects.filter(id=i.get("productID"), stock=origin_stock, count=origin_count)
                        if not good_queryset:
                            # 说明有人动了数据库， 本次创建订单就失败
                            flag += 1
                            continue
                        else:
                            break

                    if flag == 3:
                        raise ValueError("并发冲突，创建订单失败")

                    # 5.2存储订单商品信息
                    OrderGood.objects.create(good=good, count=num, price=good.selling_price, order=order)

                    # 5.3更新商品的库存
                    good.stock = origin_stock - num
                    good.count = origin_count + num
                    good.save()

                    # 统计订单的总价格、总商品数
                    total_amount += num*good.selling_price
                    total_count += num

                # 更新订单对象
                order.total_count = total_count
                order.total_amount = total_amount
                order.save()

               # 6.删除redis购物车的代码，已迁移

            except:

                # 创建订单异常，立即回滚事务
                transaction.savepoint_rollback(point)
                # 返回响应
                return Response({"code":204, 'msg':'创建订单失败'})

            # 没有异常， 创建订单成功， 提交事务
            transaction.savepoint_commit(point)

            # 生成支付地址
            total_amount = int(total_amount)
            pay_url = self.get_pay_url(order_id, total_amount)

            # 返回响应
            return Response({"code":302, 'msg':'创建订单成功,正在跳转支付页面...', 'url': pay_url})


    # 查看订单
    @check_login
    def get(self,request):
        # 1.获取用户对象
        user = request.user
        # 2.查看该用户所有的订单
        order_queryset = user.order_set.all()
        if order_queryset:
            # 3.遍历每个订单，根据订单查询订单商品
            orders = []
            for order in order_queryset:
                # 可以使用正向查询 OrderGood.objects.filter(order=order)

                # 这里采用反向查询
                order_good_queryset = order.ordergood_set.all()
                temp = []
                # 过滤空订单
                if not order_good_queryset:
                    continue

                # 4.遍历 获取每一个订单商品，组织该商品的字典结构
                for order_good in order_good_queryset:
                    order_good_dict = {
                        "productID": order_good.good.id,
                        "productName": order_good.good.sku_name,
                        "productImg": order_good.good.img,
                        "productPrice": order_good.price,
                        "productNum": order_good.count,
                        "orderID": order.order_id,
                        "createdTime": order.created_time,
                        # "payStatus":'待收货',
                        "payStatus": order.get_pay_status_display()
                    }
                    # 放入当前订单列表篇
                    temp.append(order_good_dict)

                # 当前订单 放入总体的orders 列表
                orders.append(temp)

            # 5.返回响应
            return Response({"code":200,'msg':'获取订单数据成功', 'orders': orders})

        else:
            return Response({"code":204,'msg':'用户尚未下订单',"orders":[]})


    # 保留put  给’待收货‘
    def put(self,request):
        # 1.获取前端数据
        order_id = request.data.get("orderID")

        # 2.查询当前订单
        order = Order.objects.get(order_id=order_id)

        # 3.更新状态
        status = order.pay_status
        order.pay_status = str(int(status) + 1)

        order.save()

        # 4.返回响应
        return Response({"code":200 , 'msg':'收获成功'})

    # 接受delete请求，实现订单商品的删除
    def delete(self,request):
        # 1.接受前端数据
        order_id = request.data.get("orderID")
        good_id = request.data.get("productID")

        # 2.根据order_id查询订单对象
        order = Order.objects.get(order_id=order_id)

        # 3.查询当前订单中所有的商品
        order_good_queryset = order.ordergood_set.all()

        # 4.判断订单中商品的个数，分别做出不同的删除
        if order_good_queryset.count() <= 1:
            # 删除订单商品
            order_good_queryset.delete()
            # 删除当前订单
            order.delete()

        else:
            for i in order_good_queryset:
                if i.good.id == good_id:
                    i.delete()


        return Response({"code":200, 'msg':'删除订单商品成功'})























